home *** CD-ROM | disk | FTP | other *** search
/ Personal Computer World 2009 February / PCWFEB09.iso / Software / Linux / Kubuntu 8.10 / kubuntu-8.10-desktop-i386.iso / casper / filesystem.squashfs / usr / share / python-support / install-package / install-package.py
Encoding:
Python Source  |  2008-10-15  |  11.9 KB  |  283 lines

  1. #!/usr/bin/env python
  2. # -*- coding: utf-8 -*-
  3. #
  4. # Copyright 2008 Canonical Ltd
  5. # Includes code from GDebi, Copyright 2007 Martin B├╢hm <martin.bohm@ubuntu.com>
  6. #
  7. # AUTHOR:
  8. # Jonathan Riddell <jriddell@ubuntu.com>
  9. #
  10. # This program is free software; you can redistribute it and/or
  11. # modify it under the terms of the GNU General Public License as published
  12. # by the Free Software Foundation; either version 2 of the License, or (at
  13. # your option) any later version.
  14. #
  15. # This program is distributed in the hope that it will be useful,
  16. # but WITHOUT ANY WARRANTY; without even the implied warranty of
  17. # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  18. # General Public License for more details.
  19. #
  20. # You should have received a copy of the GNU General Public License
  21. # along with this program.  If not, see <http://www.gnu.org/licenses/>.
  22.  
  23. import sys
  24.  
  25. from PyKDE4.kdecore import ki18n, KAboutData, KCmdLineArgs
  26. from PyKDE4.kdeui import KApplication, KMainWindow
  27.  
  28. from PyQt4.QtGui import *
  29. from PyQt4.QtCore import *
  30. from PyQt4 import uic
  31.  
  32. import apt_pkg
  33. from GDebi.DebPackage import DebPackage, Cache
  34. from GDebi.KDEAptDialogs import *
  35.  
  36. class DumbTerminal(QTextEdit):
  37.     """ a very dumb terminal """
  38.     def __init__(self, parent_frame):
  39.         """ really dumb terminal with simple editing support """
  40.         QTextEdit.__init__(self, parent_frame)
  41.         self.setFontFamily("Monospace")
  42.         self.setFontPointSize(8)
  43.         self.setWordWrapMode(QTextOption.NoWrap)
  44.         self.setUndoRedoEnabled(False)
  45.         self._block = False
  46.         self.connect(self, SIGNAL("cursorPositionChanged(int,int)"), self.onCursorPositionChanged)
  47.  
  48.     def setInstallProgress(self, installProgress):
  49.         self.installProgress = installProgress
  50.  
  51.     def insertWithTermCodes(self, text):
  52.         """ support basic terminal codes """
  53.         display_text = ""
  54.         for c in text:
  55.             # \b - backspace
  56.             if c == chr(8):
  57.                 self.moveCursor(QTextEdit.MoveBackward, QTextCursor.KeepAnchor)
  58.                 self.cut() #self.removeSelectedText()  FIXME
  59.             # \r - is filtered out
  60.             elif c == chr(13):
  61.                 pass
  62.             # \a - bell - ignore for now
  63.             elif c == chr(7):
  64.                 pass
  65.             else:
  66.                 display_text += c
  67.         self.insertPlainText(display_text)
  68.  
  69.     def keyPressEvent(self, ev):
  70.         """ send (ascii) key events to the pty """
  71.         # no master_fd yet
  72.         if not hasattr(self.installProgress, "master_fd"):
  73.             return
  74.         # special handling for backspace
  75.         if ev.key() == Qt.Key_Backspace:
  76.             #print "sent backspace"
  77.             os.write(self.installProgress.master_fd, chr(8))
  78.             return
  79.         # do nothing for events like "shift" 
  80.         if not ev.text():
  81.             return
  82.         # now sent the key event to the termianl as utf-8
  83.         os.write(self.installProgress.master_fd, ev.text().toUtf8())
  84.  
  85.     def onCursorPositionChanged(self, x, y):
  86.         """ helper that ensures that the cursor is always at the end """
  87.         if self._block:
  88.             return
  89.         # block signals so that we do not run into a recursion
  90.         self._block = True
  91.         para = self.paragraphs() - 1
  92.         pos = self.paragraphLength(para)
  93.         self.moveCursor(QTextCursor.End)
  94.         self._block = False
  95.  
  96. class MainWindow (QDialog):
  97.     def __init__ (self, mode, packages):
  98.         QDialog.__init__ (self)
  99.  
  100.         if os.path.exists("install-package.ui"):
  101.             APPDIR = QDir.currentPath()
  102.         else:
  103.             file = KStandardDirs.locate("appdata", "install-package.ui")
  104.             APPDIR = file.left(file.lastIndexOf("/"))
  105.         uic.loadUi(APPDIR + "/install-package.ui", self)
  106.         self.setWindowTitle(i18n("Package Install"))
  107.         self.setWindowIcon(KIcon("applications-other"))
  108.  
  109.         self.cprogress = CacheProgressAdapter(self.installationProgress)
  110.         self._cache = Cache(self.cprogress)
  111.  
  112.         self.mode = mode
  113.         action = False
  114.         self.packages = []
  115.         for package in packages:
  116.             if not package in self._cache:
  117.                 print "no such package " + package
  118.             elif mode == "install":
  119.                 if not self._cache[package].isInstalled:
  120.                     action = True
  121.                     self.packages.append(package)
  122.                     self.titleLabel.setText(i18nc("package name", "<b>Installing %1</b>", package))
  123.                     self._cache[package].markInstall()
  124.             elif mode == "uninstall":
  125.                 if self._cache[package].isInstalled:
  126.                     action = True
  127.                     self.packages.append(package)
  128.                     self.titleLabel.setText(i18nc("package name", "<b>Uninstalling %1</b>", package))
  129.                     self._cache[package].markDelete()
  130.  
  131.         if action or mode =="update":
  132.             if mode == "install":
  133.                 #need to check for plural, else it complains about too many args because the plural string doesn't use %2
  134.                 if len(self.packages) == 1:
  135.                     self.titleLabel.setText(i18ncp("package name", "<b>Installing %2</b>", "<b>Installing packages</b>", len(self.packages), self.packages[0]))
  136.                 else:
  137.                     self.titleLabel.setText(i18n("<b>Installing packages</b>"))
  138.             elif mode == "uninstall":
  139.                 if len(self.packages) == 1:
  140.                     self.titleLabel.setText(i18ncp("package name", "<b>Uninstalling %2</b>", "<b>Uninstalling packages</b>", len(self.packages), self.packages[0]))
  141.                 else:
  142.                     self.titleLabel.setText(i18n("<b>Uninstalling packages</b>"))
  143.             self.buttonBox.hide()
  144.             self.readyInstall()
  145.         else:
  146.             if mode == "install":
  147.                 if len(self.packages) == 1:
  148.                     self.titleLabel.setText(i18ncp("package name", "<b>%2 is already installed</b>", "<b>Requested packages are already installed</b>", len(packages), packages[0]))
  149.                 else:
  150.                     self.titleLabel.setText(i18n("<b>Requested packages are already installed</b>"))
  151.             elif mode == "uninstall":
  152.                 if len(self.packages) == 1:
  153.                     self.titleLabel.setText(i18ncp("package name", "<b>%2 is already uninstalled</b>", "<b>Requested packages are already uninstalled</b>", len(packages), packages[0]))
  154.                 else:
  155.                     self.titleLabel.setText(i18n("<b>Requested packages are already uninstalled</b>"))
  156.             self.installFrame.hide()
  157.         self.connect(self.buttonBox, SIGNAL("clicked(QAbstractButton*)"), self.quit)
  158.         QTimer.singleShot(10, self.resizing)
  159.  
  160.     def quit(self):
  161.         self.hide()
  162.         sys.exit() #QApplication.exit() causes a crash :(
  163.  
  164.     def readyInstall(self):
  165.         self.konsoleFrameLayout = QHBoxLayout(self.konsoleFrame)
  166.         self.newKonsole()
  167.         self.fprogress = KDEFetchProgressAdapter(self.installationProgress, self.installingLabel, self)
  168.         self.iprogress = KDEInstallProgressAdapter(self.installationProgress, self.installingLabel, self)
  169.         self.konsole.setInstallProgress(self.iprogress)
  170.         self.showDetailsButton.setText(i18n("Show Details >>>"))
  171.         if self.mode == "update":
  172.             self.showDetailsButton.hide()
  173.         self.konsoleFrame.hide()
  174.         self.connect(self.showDetailsButton, SIGNAL("clicked()"), self.showDetails)
  175.         self.installationProgress.setValue(0)
  176.         QTimer.singleShot(1000, self.commit)
  177.  
  178.     def newKonsole(self):
  179.         self.konsole = DumbTerminal(self.konsoleFrame)
  180.         self.konsoleFrame.setMinimumSize(500, 400)
  181.         self.konsoleFrameLayout.addWidget(self.konsole)
  182.  
  183.     def showDetails(self):
  184.         if self.konsoleFrame.isVisible():
  185.             self.konsoleFrame.hide()
  186.             self.showDetailsButton.setText(i18n("Show Details >>>"))
  187.             QTimer.singleShot(10, self.resizing)
  188.         else:
  189.             self.konsoleFrame.show()
  190.             self.showDetailsButton.setText(i18n("<<< Hide Details"))
  191.  
  192.     def resizing(self):
  193.         self.resize(self.minimumSizeHint())
  194.  
  195.     def commit(self):
  196.         apt_pkg.PkgSystemLock()
  197.         if self.mode == "update":
  198.             result = self._cache.update(self.fprogress)
  199.         else:
  200.             result = self._cache.commit(self.fprogress,self.iprogress)
  201.         if result:
  202.             if self.mode == "install":
  203.                 if len(self.packages) == 1:
  204.                     self.titleLabel.setText(i18ncp("package name", "<b>%2 successfully installed</b>", "<b>Successfully installed</b>", len(self.packages), self.packages[0]))
  205.                 else:
  206.                     self.titleLabel.setText(i18n("<b>Successfully installed</b>"))
  207.             elif self.mode == "uninstall":
  208.                 if len(self.packages) == 1:
  209.                     self.titleLabel.setText(i18ncp("package name", "<b>%2 successfully uninstalled</b>", "<b>Successfully installed</b>", len(self.packages), self.packages[0]))
  210.                 else:
  211.                     self.titleLabel.setText(i18n("<b>Successfully installed</b>"))
  212.             elif self.mode == "update":
  213.                 self.titleLabel.setText(i18n("<b>Successfully updated</b>"))
  214.             self.installFrame.hide()
  215.         else:
  216.             if self.mode == "install":
  217.                 if len(self.packages) == 1:
  218.                     self.titleLabel.setText(i18ncp("package name", "<b>Failed to install package '%2'</b>", "<b>Failed to install packages</b>", len(self.packages), self.packages[0]))
  219.                 else:
  220.                     self.titleLabel.setText(i18n("<b>Failed to install packages</b>"))
  221.             elif self.mode == "uninstall":
  222.                 if len(self.packages) == 1:
  223.                     self.titleLabel.setText(i18ncp("package name", "<b>Failed to uninstall package '%2'</b>", "<b>Failed to uninstall packages</b>", len(self.packages), self.packages[0]))
  224.                 else:
  225.                     self.titleLabel.setText(i18n("<b>Failed to uninstall packages</b>"))
  226.             elif self.mode == "update":
  227.                 self.titleLabel.setText(i18n("<b>Failed to update</b>"))
  228.         self.buttonBox.show()
  229.         QTimer.singleShot(10, self.resizing)
  230.  
  231. if __name__ == '__main__':
  232.  
  233.     appName     = "install-package"
  234.     catalog     = ""
  235.     programName = ki18n ("Install Package")
  236.     version     = "1.0"
  237.     description = ki18n ("Installs a package")
  238.     license     = KAboutData.License_GPL
  239.     copyright   = ki18n ("(c) 2008 Canonical Ltd")
  240.     text        = ki18n ("")
  241.     homePage    = "http://launchpad.net/install-package"
  242.     bugEmail    = ""
  243.  
  244.     aboutData   = KAboutData(appName, catalog, programName, version, description, license, copyright, text, homePage, bugEmail)
  245.  
  246.     options = KCmdLineOptions()
  247.     options.add("install", ki18n("Install a package"))
  248.     options.add("uninstall", ki18n("Uninstall a package"))
  249.     options.add("update", ki18n("Reload package list"))
  250.     options.add("!+packages", ki18n("Packages to install/uninstall"))
  251.  
  252.     KCmdLineArgs.init(sys.argv, aboutData)
  253.     KCmdLineArgs.addCmdLineOptions(options)
  254.  
  255.     app = KApplication()
  256.     args = KCmdLineArgs.parsedArgs()
  257.  
  258.     packages = []
  259.     if args.isSet("install") and args.count() > 0:
  260.         mode = "install"
  261.     elif args.isSet("uninstall") and args.count() > 0:
  262.         mode = "uninstall"
  263.     elif args.isSet("update"):
  264.         mode = "update"
  265.     else:
  266.         print "Usage: install-package --install <package>, or, --uninstall <package>"
  267.         KMessageBox.sorry(None, i18n("Usage: install-package --install <package>, or, --uninstall <package>"), i18n("Command Use"), KMessageBox.Notify)
  268.         sys.exit(1)
  269.  
  270.     for item in range(args.count()):
  271.         packages.append(unicode(args.arg(item)))
  272.  
  273.     if os.geteuid() != 0:
  274.         text = i18n("Please run this software with administrative rights. To do so, run this program with kdesudo.")
  275.         title = i18n("Need administrative powers")
  276.         KMessageBox.sorry(None, text, title, KMessageBox.Notify)
  277.         sys.exit(1)
  278.  
  279.     mainWindow = MainWindow(mode, packages)
  280.     mainWindow.show()
  281.  
  282.     app.exec_()
  283.